/**
 * @author Xiao Xin
 * @version 1.0.0
 * @date 20210311
 * @copyright MIN-Group:国家重大科技基础设施-未来网络北大实验室：深圳市信息论与未来网络重点实验室
 */
var SelfEncodingBase = require('../encoding/SelfEncodingBase').SelfEncodingBase
var Encoder = require('../encoding/Encoder').Encoder
var Block = require('../encoding/Block').Block
var TLV = require('../encoding/TLV')
var {TlvComponentBase} = require('./TlvComponentBase')
var aggregation = require('../common/aggregation')//实现了多继承

 /**
  * @description 表示一个MIN包格式中的可变非保护区
  */
 class MutableDangerousField extends aggregation(TlvComponentBase,SelfEncodingBase){
  constructor(){
    super()
    this.blocks = new Array()//存放block的数组
  }

   /**
   * @description 往可变非保护区添加一个Block
   * @param {Block} block
   */
  addBlock(block){
    this.blocks.push(block)
  }

  /**
   * @description 获取可变非保护区指定位置的 Block
   * @param {number}index
   * @return {Block}
   */
  getBlock(index){
    if(index >= this.blocks.length){
      throw new MutableDangerousFieldError("Out of range of blocks")
    }
    return this.blocks[index]
  }

  /**
   * @description 清空可变非保护区中，所有的子 Block
   */
  clearBlocks(){
    this.blocks.length = 0
  }

  /**
   * @description 获取可变非保护区所有的 Block
   * @return {[]Block}
   */
  getBlocks(){
    return this.blocks
  }

  /**
   * @description 获取可变非保护区中，第一个指定 TLV-TYPE 的子 TLV Block
   * @param {number} tlvtype
   * @return {Block}
   */
  getBlockByType(tlvType){
    for(var element of this.blocks){
      if(element.getType() == tlvType){
        return element
      }
    }
  }

  /**
   * @description 将可变非保护区线速编码为一个 TLV
   * @param {Encoder} encoder
   * @param {number}
   */
  wireEncode(encoder){
    // 如果可变非保护区没有任何子 TLV ，则可以去掉可变非保护区 TLV
    if(this.blocks.length == 0){
      return 0
    }
    var totalLength = 0
    // 编码 TLV-VALUE
    // 反向遍历，可以保证解码的时候正向输出
    for(let i = this.blocks.length-1; i >= 0;i --){
      try {
        let tmpLen = encoder.prependBlock(this.blocks[i])
        totalLength += tmpLen
      } catch (error) {
        throw error
      }
    }
    
    try {
      //编码 TLV-LENGTH
      let tmpLen = encoder.prependVarNumber(BigInt(totalLength))
      totalLength += tmpLen
      
      //编码 TLV-TYPE
      tmpLen = encoder.prependVarNumber(TLV.FieldType.TlvMutableDangerousField)
      totalLength += tmpLen
      return totalLength
    } catch (error) {
      throw error
    }
  }

  /**
   * @description 从 TLV Block中解码初一个 MutableDangerousField
   * @param {Block} Block
   */
  wireDecode(block){
    try {
      //检查 TYPE 是否正确
      TLV.expectType(block.getType(),TLV.FieldType.TlvMutableDangerousField)

      //解析子 TLV
      block.parseSubElements()
      this.blocks = block.getSubElements()
    } catch (error) {
      throw error
    }
  }
 }

 //错误处理
class MutableDangerousFieldError{
  constructor(m){
    this.msg = m || ""
  }

  static error(){
    console.log("MutableDangerousFieldError: "+this.msg)
  }
}

module.exports = {
  MutableDangerousField: MutableDangerousField,
  MutableDangerousFieldError: MutableDangerousFieldError
}